#pragma once
#include <windows.h>

#include <dp/sys/common.h>

DP_BEGIN

// http://en.wikipedia.org/wiki/Atomic_operation
// return void thay vi LONG:
//	Cac atomic APIs thuong return 1 value voi nhieu nghia khac nhau, rat de gay hieu nham
//	vi vay chung ta se khong dung cac return value.
class Interlock
{
public:
	Interlock(LONG data = 0)
		: m_data(data)
	{		
	}

	void operator ++()
	{
		// The return value is too complicated, so we decided to not return.
		//MS: The function returns the resulting incremented value. 
		//	Windows NT 3.51 and earlier and Windows 95:  If the result of the operation is zero, 
		//	the return value is zero. If the result of the operation is less than zero, the return 
		//	value is negative, but it is not necessarily equal to the result. If the result of the 
		//	operation is greater than zero, the return value is positive, but it is not necessarily 
		//	equal to the result.
		InterlockedIncrement(&m_data);
	}

	void operator --()
	{
		InterlockedDecrement(&m_data);
	}

	void operator += (LONG val)
	{
		// The return value is too complicated, so we decided to not return.
		// MS: The function returns the initial value of the Addend parameter.
		InterlockedExchangeAdd(&m_data, val);
	};

	void operator -= (LONG val)
	{
		//The function returns the initial value of the Addend parameter.
		InterlockedExchangeAdd(&m_data, -val);
	};

	// TODO: add anothers methods here (see MSDN)
	operator LONG()
	{
		// Hoi: nen copy ra mot bien tam truoc khi return?
		// Vi viec copy 1 bien chua chac la atomic operation
		return m_data;
	}

private:
	volatile LONG m_data;
};

DP_END